#if $str($getVar('mco_auto_setup','')) == "1"
mkdir -p /etc/mcollective
cat <<EOCONF > /etc/mcollective/server.cfg
main_collective = mcollective
collectives = mcollective
libdir = /usr/libexec/mcollective
logfile = /var/log/mcollective.log
loglevel = info
daemonize = 0
direct_addressing = 1

# Plugins
securityprovider = psk
plugin.psk = $mco_pskey

connector = rabbitmq
plugin.rabbitmq.vhost = mcollective
plugin.rabbitmq.pool.size = 1
plugin.rabbitmq.pool.1.host = $mco_stomphost
plugin.rabbitmq.pool.1.port = $mco_stompport
plugin.rabbitmq.pool.1.user = $mco_stompuser
plugin.rabbitmq.pool.1.password = $mco_stomppassword

# Facts
factsource = yaml
plugin.yaml = /etc/mcollective/facts.yaml
EOCONF

cat <<EOCONF >> /etc/supervisord.conf
[program:mcollective]
command=/usr/sbin/mcollectived --config=/etc/mcollective/server.cfg
autostart=true
EOCONF

cat <<EOCONF > /usr/libexec/mcollective/mcollective/agent/puppetd.ddl
metadata    :name        => "puppetd",
            :description => "Run puppet agent, get its status, and enable/disable it",
            :author      => "R.I.Pienaar",
            :license     => "Apache License 2.0",
            :version     => "1.8",
            :url         => "https://github.com/puppetlabs/mcollective-plugins",
            :timeout     => 240

action "last_run_summary", :description => "Get a summary of the last puppet run" do
    display :always

    output :time,
           :description => "Time per resource type",
           :display_as => "Times"
    output :resources,
           :description => "Overall resource counts",
           :display_as => "Resources"

    output :changes,
           :description => "Number of changes",
           :display_as => "Changes"

    output :events,
           :description => "Number of events",
           :display_as => "Events"

    output :version,
           :description => "Puppet and Catalog versions",
           :display_as => "Versions"
end

action "enable", :description => "Enable puppet agent" do
    output :output,
           :description => "String indicating status",
           :display_as => "Status"
end

action "disable", :description => "Disable puppet agent" do
    output :output,
           :description => "String indicating status",
           :display_as => "Status"
end

action "runonce", :description => "Invoke a single puppet run" do
    #input :forcerun,
    #    :prompt      => "Force puppet run",
    #    :description => "Should the puppet run happen immediately?",
    #    :type        => :string,
    #    :validation  => '^.+$',
    #    :optional    => true,
    #    :maxlength   => 5

    output :output,
           :description => "Output from puppet agent",
           :display_as => "Output"
end

action "status", :description => "Get puppet agent's status" do
    display :always

    output :status,
           :description => "The status of the puppet agent: disabled, running, idling or stopped",
           :display_as => "Status"

    output :enabled,
           :description => "Whether puppet agent is enabled",
           :display_as => "Enabled"

    output :running,
           :description => "Whether puppet agent is running",
           :display_as => "Running"

    output :idling,
           :description => "Whether puppet agent is idling",
           :display_as => "Idling"

    output :stopped,
           :description => "Whether puppet agent is stopped",
           :display_as => "Stopped"

    output :lastrun,
           :description => "When puppet agent last ran",
           :display_as => "Last Run"

    output :output,
           :description => "String displaying agent status",
           :display_as => "Status"
end
EOCONF

cat <<EOCONF > /usr/libexec/mcollective/mcollective/agent/puppetd.rb
module MCollective
  module Agent
    # An agent to manage the Puppet Daemon
    #
    # Configuration Options:
    #    puppetd.splaytime - Number of seconds within which to splay; no splay
    #                        by default
    #    puppetd.statefile - Where to find the state.yaml file; defaults to
    #                        /var/lib/puppet/state/state.yaml
    #    puppetd.lockfile  - Where to find the lock file; defaults to
    #                        /var/lib/puppet/state/puppetdlock
    #    puppetd.puppetd   - Where to find the puppet agent binary; defaults to
    #                        /usr/bin/puppet agent
    #    puppetd.summary   - Where to find the summary file written by Puppet
    #                        2.6.8 and newer; defaults to
    #                        /var/lib/puppet/state/last_run_summary.yaml
    #    puppetd.pidfile   - Where to find puppet agent's pid file; defaults to
    #                        /var/run/puppet/agent.pid
    class Puppetd<RPC::Agent
      def startup_hook
        @splaytime = @config.pluginconf["puppetd.splaytime"].to_i || 0
        @lockfile = @config.pluginconf["puppetd.lockfile"] || "/var/lib/puppet/state/puppetdlock"
        @statefile = @config.pluginconf["puppetd.statefile"] || "/var/lib/puppet/state/state.yaml"
        @pidfile = @config.pluginconf["puppet.pidfile"] || "/var/run/puppet/agent.pid"
        @puppetd = @config.pluginconf["puppetd.puppetd"] || "/usr/bin/puppet agent"
        @last_summary = @config.pluginconf["puppet.summary"] || "/var/lib/puppet/state/last_run_summary.yaml"
      end

      action "last_run_summary" do
        last_run_summary
        set_status
      end

      action "enable" do
        enable
      end

      action "disable" do
        disable
      end

      action "runonce" do
        runonce
      end

      action "status" do
        set_status
      end

      private
      def last_run_summary
        # wrap into begin..rescue: fixes PRD-252
        begin
          summary = YAML.load_file(@last_summary)
        rescue
          summary = {}
        end

        # It should be empty hash, if 'resources' key is not defined, because otherwise merge will fail with TypeError
        summary["resources"] ||= {}
        # Astute relies on last_run, so we must set last_run
        summary["time"] ||= {}
        summary["time"]["last_run"] ||= 0
        # if 'failed' is not provided, it means something is wrong. So default value is 1.
        reply[:resources] = {"failed"=>1, "changed"=>0, "total"=>0, "restarted"=>0, "out_of_sync"=>0}.merge(summary["resources"])

        ["time", "events", "changes", "version"].each do |dat|
          reply[dat.to_sym] = summary[dat]
        end
      end

      def set_status
        reply[:status]  = puppet_daemon_status
        reply[:running] = reply[:status] == 'running'  ? 1 : 0
        reply[:enabled] = reply[:status] == 'disabled' ? 0 : 1
        reply[:idling]  = reply[:status] == 'idling'   ? 1 : 0
        reply[:stopped] = reply[:status] == 'stopped'  ? 1 : 0
        reply[:lastrun] = 0
        reply[:lastrun] = File.stat(@statefile).mtime.to_i if File.exists?(@statefile)
        reply[:runtime] = Time.now.to_i - reply[:lastrun]
        reply[:output]  = "Currently #{reply[:status]}; last completed run #{reply[:runtime]} seconds ago"
      end

      def rm_file file
        begin
          File.unlink(file)
          return true
        rescue
          return false
        end
      end

      def puppet_daemon_status
        err_msg = ""
        alive = false
        if File.exists?(@pidfile)
          pid = File.read(@pidfile)
          begin
            ::Process.kill(0, Integer(pid)) # check that pid is alive
          alive = true
          rescue
            err_msg << "Pidfile is present but process not running. Trying to remove pidfile..."
            err_msg << (rm_file(@pidfile) ? "ok. " : "failed. ")
          end
        end

        locked = File.exists?(@lockfile)
        disabled = locked && File::Stat.new(@lockfile).zero?
        if locked && !disabled && !alive
          err_msg << "Process not running but not empty lockfile is present. Trying to remove lockfile..."
          err_msg << (rm_file(@lockfile) ? "ok." : "failed.")
        end

        reply[:err_msg] = err_msg if err_msg.any?

        if disabled
          'disabled'
        elsif alive && locked
          'running'
        elsif alive && !locked
          'idling'
        elsif !alive
          'stopped'
        end
      end

      def runonce
        set_status
        case (reply[:status])
        when 'disabled' then     # can't run
          reply.fail "Empty Lock file exists; puppet agent is disabled."

        when 'running' then      # can't run two simultaniously
          reply.fail "Lock file and PID file exist; puppet agent is running."

        when 'idling' then       # signal daemon
          pid = File.read(@pidfile)
          if pid !~ /^\d+$/
            reply.fail "PID file does not contain a PID; got #{pid.inspect}"
          else
            begin
              ::Process.kill(0, Integer(pid)) # check that pid is alive
              # REVISIT: Should we add an extra round of security here, and
              # ensure that the PID file is securely owned, or that the target
              # process looks like Puppet?  Otherwise a malicious user could
              # theoretically signal arbitrary processes with this...
              begin
                ::Process.kill("USR1", Integer(pid))
                reply[:output] = "Signalled daemonized puppet agent to run (process #{Integer(pid)}); " + (reply[:output] || '')
              rescue Exception => e
                reply.fail "Failed to signal the puppet agent daemon (process #{pid}): #{e}"
              end
            rescue Errno::ESRCH => e
              # PID is invalid, run puppet onetime as usual
              runonce_background
            end
          end

        when 'stopped' then      # just run
          runonce_background

        else
          reply.fail "Unknown puppet agent status: #{reply[:status]}"
        end
      end

      def runonce_background
        cmd = [@puppetd, "--onetime", "--logdest", 'syslog']

        unless request[:forcerun]
          if @splaytime && @splaytime > 0
            cmd << "--splaylimit" << @splaytime << "--splay"
          end
        end

        cmd = cmd.join(" ")

        output = reply[:output] || ''
        run(cmd, :stdout => :output, :chomp => true)
        reply[:output] = "Called #{cmd}, " + output + (reply[:output] || '')
      end

      def enable
        if File.exists?(@lockfile)
          stat = File::Stat.new(@lockfile)

          if stat.zero?
            File.unlink(@lockfile)
            reply[:output] = "Lock removed"
          else
            reply[:output] = "Currently running; can't remove lock"
          end
        else
          reply.fail "Already enabled"
        end
      end

      def disable
        if File.exists?(@lockfile)
          stat = File::Stat.new(@lockfile)

          stat.zero? ? reply.fail("Already disabled") : reply.fail("Currently running; can't remove lock")
        else
          begin
            File.open(@lockfile, "w") { |file| }

            reply[:output] = "Lock created"
          rescue Exception => e
            reply.fail "Could not create lock: #{e}"
          end
        end
      end
    end
  end
end

# vi:tabstop=2:expandtab:ai:filetype=ruby
EOCONF

# turn off ttl check in mcollective
find / -name message.rb | grep mcollective | xargs sed -i 's/msg_age = Time.now.utc.to_i - msgtime/msg_age = 0 #Time.now.utc.to_i - msgtime/g'

#end if

#if $str($getVar('mco_enable', '')) == "1"
## turn on mcollective service after reboot
## /sbin/chkconfig mcollective on
## service mcollective restart
/sbin/chkconfig mcollective off
/sbin/chkconfig supervisord on
#end if
